package org.one.stone.soup.grfxML;

import java.awt.BasicStroke;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.Polygon;
import java.awt.Stroke;

import org.one.stone.soup.mjdb.data.field.BoolField;
import org.one.stone.soup.mjdb.data.field.FloatField;
import org.one.stone.soup.mjdb.data.field.IntField;
import org.one.stone.soup.mjdb.data.field.Point2DField;
import org.one.stone.soup.xml.XmlElement;
  /*
 * Copyright 2000-2001 Wet-Wired.com Ltd.,
 * Portsmouth England
 * All rights reserved.
 */

/**
	*
	* @author Nik Cross
*/
public class GeometryPolygon extends Geometry{

	DataPoint windowField;
	DataPoint boundsField;

	BoolField visibleField;

	FloatField transparencyField;
	boolean transparent;

	DataColor colorField;
	Color color;

	BoolField filledField;
	boolean filled;

	BoolField closedField;
	boolean closed;

	Point2DField offsetField;
	Point2DField positionField;

	DataPoints pointsField;

	DataSize thicknessField;
	BasicStroke thickness;

	protected Polygon polygon = new Polygon();
	private int[] pointsX;
	private int[] pointsY;
	int minX,maxX;
	int minY,maxY;
public GeometryPolygon(
		GrfxMLEngine engine,
		DataPoint windowF,
		DataPoint boundsF,
		BoolField visibleF,
		FloatField transparencyF,
		DataColor colorF,
		BoolField filledF,
		BoolField closedF,
		Point2DField positionF,
		Point2DField offsetF,
		DataPoints pointsF,
		DataSize thicknessF
		) {
	super(engine);

	windowField = windowF;
	boundsField = boundsF;
	visibleField = visibleF;
	transparencyField = transparencyF;
	colorField = colorF;
	filledField = filledF;
	closedField = closedF;
	positionField = positionF;
	offsetField = offsetF;
	pointsField = pointsF;
	thicknessField = thicknessF;

	process(true);
}
/**
 * contains method comment.
 */
public boolean contains(Point2DField point,Point2DField pointView) {

	if(visibleField.getValue()==false)
		return false;

	if(closedField.getValue()==false)
		return false;

	int pX = pointView.getValueX();
	int pY = pointView.getValueY();
	if(pX<minX || pY<minY || pX>maxX || pY>maxY)
	{
		return false;
	}

	return polygon.contains(pX,pY);
}
public void draw(Graphics grfx)
{
	if(visibleField.getValue()==false)
		return;

	if(visibleField.hasChanged())
		process(true);
	else
		process(false);

	if(transparencyField.getValue()==1)
		return;

	grfx.setClip(
		windowField.getValueXMin(),
		windowField.getValueYMin(),
		windowField.getValueX(),
		windowField.getValueY()
	);

	grfx.setColor(color);
	if(!closed)
	{
		Stroke stroke = ((Graphics2D)grfx).getStroke();
		((Graphics2D)grfx).setStroke( thickness );

		grfx.drawPolyline(pointsX,pointsY,pointsX.length);

		((Graphics2D)grfx).setStroke( stroke );
	}
	else if(polygon.npoints>0)
	{
		if(filled)
		{
			grfx.fillPolygon(polygon);
		}
		else
		{
			grfx.drawPolygon(polygon);
		}
	}
}
/**
 *
 * @return java.awt.Polygon
 */
protected Polygon getPolygon() {
	return polygon;
}
public void process(boolean forced)
{
	if(forced==true)
	{
		color = GrfxMLProcessor.getColorFor(colorField);
		filled = filledField.getValue();
		closed = closedField.getValue();

//		int x = positionField.getValueX()+offsetField.getValueX();
//		int y = positionField.getValueY()+offsetField.getValueY();
		int x = offsetField.getValueX();
		int y = offsetField.getValueY();

		pointsX = new int[pointsField.size()];
		pointsY = new int[pointsField.size()];

		minX = IntField.INT_MAX_POS;
		minY = IntField.INT_MAX_POS;
		maxX = IntField.INT_MAX_NEG;
		maxY = IntField.INT_MAX_NEG;
		for(int loop=0;loop<pointsField.size();loop++)
		{
			pointsX[loop] = pointsField.get(loop).getValueX()+x;
			pointsY[loop] = pointsField.get(loop).getValueY()+y;

			if(loop==0)
			{
				minX=pointsX[loop];
				minY=pointsY[loop];
			}

			if(minX>pointsX[loop])
				minX=pointsX[loop];
			if(minY>pointsY[loop])
				minY=pointsY[loop];
			if(maxX<pointsX[loop])
				maxX=pointsX[loop];
			if(maxY<pointsY[loop])
				maxY=pointsY[loop];
		}

		boundsField.setValueXMin(minX);
		boundsField.setValueYMin(minY);

		boundsField.setValueXMax(maxX-2);
		boundsField.setValueYMax(maxY-2);

		boundsField.update();

		polygon = new Polygon(pointsX,pointsY,pointsField.size());

		if(thicknessField.getValue()<1)
		{
			thickness = new BasicStroke( 1 );
		}
		else
		{
			thickness = new BasicStroke( thicknessField.getValue(),BasicStroke.CAP_ROUND,BasicStroke.JOIN_BEVEL );
		}
	}
	else
	{
		if(colorField.hasChanged())
		{
			color = GrfxMLProcessor.getColorFor(colorField);
		}

		if(thicknessField.hasChanged())
		{
			if(thicknessField.getValue()<1)
			{
				thickness = new BasicStroke( 1 );
			}
			else
			{
				thickness = new BasicStroke( thicknessField.getValue() );
			}
		}

		if(filledField.hasChanged())
		{
			filled = filledField.getValue();
		}

		if(closedField.hasChanged())
		{
			closed = closedField.getValue();
		}

		if(offsetField.hasChanged() || pointsField.hasChanged() || positionField.hasChanged())
		{
//			int x = positionField.getValueX()+offsetField.getValueX();
//			int y = positionField.getValueY()+offsetField.getValueY();
			int x = offsetField.getValueX();
			int y = offsetField.getValueY();

			pointsX = new int[pointsField.size()];
			pointsY = new int[pointsField.size()];

			minX =0;
			minY =0;
			maxX =0;
			maxY =0;
			for(int loop=0;loop<pointsField.size();loop++)
			{
				pointsX[loop] = pointsField.get(loop).getValueX()+x;
				pointsY[loop] = pointsField.get(loop).getValueY()+y;

				if(minX>pointsX[loop])
					minX=pointsX[loop];
				if(minY>pointsY[loop])
					minY=pointsY[loop];
				if(maxX<pointsX[loop])
					maxX=pointsX[loop];
				if(maxY<pointsY[loop])
					maxY=pointsY[loop];
			}

			boundsField.setValueXMin(minX);
			boundsField.setValueYMin(minY);

			boundsField.setValueXMax(maxX-2);
			boundsField.setValueYMax(maxY-2);

			boundsField.update();

			polygon = new Polygon(pointsX,pointsY,pointsField.size());
		}
	}
}
/**
 *
 * @return java.lang.String
 */
public XmlElement toXML() {
	XmlElement element = new XmlElement("Polygon");

	if(getId()!=null)
		element.addAttribute("id",getId());

	element.addAttribute("visible",""+visibleField.getValue());
	element.addAttribute("transparency",""+transparencyField.getValue());

	element.addAttribute("red",""+colorField.getValueX());
	element.addAttribute("green",""+colorField.getValueY());
	element.addAttribute("blue",""+colorField.getValueZ());

	element.addAttribute("filled",""+filledField.getValue());
	element.addAttribute("closed",""+closedField.getValue());

	for(int loop=0;loop<pointsX.length;loop++)
	{
		XmlElement point = element.addChild("point");
		point.addAttribute("x",""+pointsX[loop]);
		point.addAttribute("y",""+pointsY[loop]);
	}

	XmlElement bounds = element.addChild("Clip");
	bounds.addAttribute( "x",""+windowField.getValueXMin() );
	bounds.addAttribute( "y",""+windowField.getValueYMin() );
	bounds.addAttribute( "width",""+windowField.getValueX() );
	bounds.addAttribute( "height",""+windowField.getValueY() );

	return element;
}

public boolean hasChanged()
{
	if(
	        windowField.hasChanged()==true ||
	        boundsField.hasChanged()==true ||
	        visibleField.hasChanged()==true ||
	        transparencyField.hasChanged()==true ||
	        colorField.hasChanged()==true ||
	        filledField.hasChanged()==true ||
	        positionField.hasChanged()==true ||
	        offsetField.hasChanged()==true ||
	        positionField.hasChanged()==true ||
	        offsetField.hasChanged()==true ||
	        pointsField.hasChanged()==true ||
	        thicknessField.hasChanged()==true
	)
	{
	    return true;
	}
	
	return false;
}

public void resetChanged()
{
    windowField.resetChanged();
    boundsField.resetChanged();
    visibleField.resetChanged();
    transparencyField.resetChanged();
    colorField.resetChanged();
    filledField.resetChanged();
    positionField.resetChanged();
    offsetField.resetChanged();
    positionField.resetChanged();
    offsetField.resetChanged();
    pointsField.resetChanged();
    thicknessField.resetChanged();
}

}
